
#ifndef __EMBEDED_BROWSER_SINK_H__
#define __EMBEDED_BROWSER_SINK_H__

#include "ZEmbededBrowser.h"
#include "HtmlWindowSink.h"

class CBrowserWnd: public CWindowImpl<CBrowserWnd>
{
public:
	ZEmbededBrowser         *m_winBrowserHost;
	BEGIN_MSG_MAP(CBrowserWnd)
		MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
		MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
	END_MSG_MAP()
		LRESULT OnSetFocus(
		_In_ UINT /*uMsg*/,
		_In_ WPARAM /*wParam*/,
		_In_ LPARAM /*lParam*/,
		_Inout_ BOOL& bHandled)
	{
		OutputDebugString("CBrowserWnd OnSetFocus\n");
		bHandled = FALSE;
		return 0;
	}
	LRESULT OnKillFocus(
		_In_ UINT /*uMsg*/,
		_In_ WPARAM /*wParam*/,
		_In_ LPARAM /*lParam*/,
		_Inout_ BOOL& bHandled)
	{
		m_winBrowserHost->PostMessage(WM_CLOSE);
		OutputDebugString("CBrowserWnd OnKillFocus\n");
		bHandled = FALSE;
		return 0;
	}
};
class ATL_NO_VTABLE CEmbededBrowserSink:
	public CComObjectRootEx<CComSingleThreadModel>,
	public IDispatch
{
public:
	CComPtr<IWebBrowser2>   m_spWebBrowser;
	CComPtr<IUnknown>       m_spUnkSink;
	DWORD				    m_dwSinkCookie;	

	ZEmbededBrowser         *m_winBrowserHost;
	CString					m_strCurrentUrl;
	CBrowserWnd				m_BrowserWnd;
	CEmbededBrowserSink(): m_spWebBrowser (NULL),
		m_spUnkSink(NULL),
		m_dwSinkCookie(0)
	{
	}

BEGIN_COM_MAP(CEmbededBrowserSink)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY_IID(DIID_DWebBrowserEvents2, IDispatch)
END_COM_MAP()

// IDispatch
public:
	STDMETHOD (GetTypeInfoCount) (UINT* pctinfo)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD (GetTypeInfo) (UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD (GetIDsOfNames) (REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
	{
		return	E_NOTIMPL;
	}
	void OnBeforeNavigate(LPDISPATCH pDisp, LPCTSTR szUrl)
	{
		szUrl; // unused
		
		if (pDisp != m_spWebBrowser)
			return;
		DisconnectHTMLWindowEvents();
	}
	void DisconnectHTMLWindowEvents()
	{
		if (m_spUnkSink == NULL)
			return;
		HRESULT hr;
		CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spHTML;
		CComPtr<IHTMLWindow2>	spHTMLWindow;
		CComPtr<IDispatch> pdispDoc = NULL;
		hr = m_spWebBrowser->get_Document(&pdispDoc);
		if (SUCCEEDED(hr ) && pdispDoc){
			spHTML = pdispDoc ;
			ATLASSERT(spHTML);
			if (SUCCEEDED(hr = spHTML->get_parentWindow(&spHTMLWindow))){
				hr = AtlUnadvise(spHTMLWindow, DIID_HTMLWindowEvents2, m_dwSinkCookie);
				ATLASSERT(SUCCEEDED(hr));
				m_spUnkSink = NULL;
				m_dwSinkCookie = 0 ;
			}
		}
	}
	void ConnectHTMLWindowEvents()
	{
		CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spHTML;
		CComPtr<IDispatch> pdispDoc = NULL;
		CComPtr<IHTMLWindow2>	spHTMLWindow;
		CComObject<CHtmlWindowSink> *pObj =NULL;
		HRESULT hr = m_spWebBrowser->get_Document(&pdispDoc);
		if (SUCCEEDED(hr )){
			spHTML = pdispDoc ;
			ATLASSERT(spHTML);

			if (SUCCEEDED(hr = spHTML->get_parentWindow(&spHTMLWindow))){
				hr = CComObject<CHtmlWindowSink>::CreateInstance(&pObj);
				if( SUCCEEDED(hr)){
					hr = pObj->QueryInterface(IID_IUnknown,(void**)&m_spUnkSink);
					if( SUCCEEDED(hr)){
						hr = AtlAdvise(spHTMLWindow,m_spUnkSink,DIID_HTMLWindowEvents2,&m_dwSinkCookie);
						if( SUCCEEDED(hr)){
							pObj->m_spWebBrowser = m_spWebBrowser;
							pObj->m_winBrowserHost = m_winBrowserHost ;
							m_winBrowserHost->m_bDocumentCompleted = TRUE;
						} else {
							ATLTRACE("AtlAdvise Failed , HRESULT %x\n",hr);
						}
					}
				}
			}
		}
	}
	void OnNavigateComplete(LPDISPATCH pDisp, LPCTSTR szUrl)
	{
		if (pDisp != m_spWebBrowser)
			return;
		HWND hChild;
		HWND hWnd;
		CHAR czClassName[256];
		int iCount;
		CString str;
		hChild=m_winBrowserHost->GetWindow(GW_CHILD);
		while(hChild){
			
			iCount = ::GetClassName(hChild,czClassName,256);
			if( _tcscmp("Internet Explorer_Server",czClassName) == 0){
				hWnd = hChild;
				break;
			}
			if( iCount > 0){
				str.Format("%s\n",czClassName);
				OutputDebugString(str);
			}
			
			hChild=::GetWindow(hChild,GW_CHILD);
		}
		if( hWnd && m_BrowserWnd != hWnd ){
			m_BrowserWnd.m_winBrowserHost = m_winBrowserHost ;
			m_BrowserWnd.SubclassWindow(hWnd);
		}
		ConnectHTMLWindowEvents();
	}

	void OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR szUrl)
	{
		szUrl; // unused
		m_strCurrentUrl = szUrl;
		if (pDisp != m_spWebBrowser)
			return;	
	}
	STDMETHOD (Invoke) (DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, 
		DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
	{
		HRESULT hr = S_OK;
		CComPtr<IDispatch> pDisp;
		UINT nArgIndex =pdispparams->cArgs-1;
		
		CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spHTML;
		VARIANT* pvarString;
		CString str;
		str.Format("dispidMember %d \n",dispidMember);
		//OutputDebugString(str);
		
		IDispatch *pDispatch = NULL;
		
		if (pdispparams)
		{
			switch (dispidMember)
			{
			// When a request comes in asking for a new window, navigate to the 
			// URL specified in the request, but within the old web browser window.
			case DISPID_NEWWINDOW:
				if (m_spWebBrowser)
				{
					VARIANT defArg; defArg.vt = VT_ERROR; defArg.scode = DISP_E_PARAMNOTFOUND;
					m_spWebBrowser->Navigate(pdispparams->rgvarg[5].bstrVal, &defArg, &defArg, pdispparams->rgvarg[2].pvarVal, &defArg);
				}
				*(pdispparams->rgvarg[0].pboolVal) = VARIANT_TRUE;
				hr = S_OK;
				break;
			case DISPID_DOCUMENTCOMPLETE:
				pDispatch = (IDispatch *)(pdispparams->rgvarg[nArgIndex--].punkVal);
				pvarString = (VARIANT*)(pdispparams->rgvarg[nArgIndex].byref);
				OnDocumentComplete(pDispatch,CString(V_BSTR(pvarString)));
				break;
			case DISPID_NAVIGATECOMPLETE2:
				pDispatch = (IDispatch *)(pdispparams->rgvarg[nArgIndex--].punkVal);
				pvarString = (VARIANT*)(pdispparams->rgvarg[nArgIndex].byref);
				OnNavigateComplete(pDispatch,CString(V_BSTR(pvarString)));
				OutputDebugString("DISPID_NAVIGATECOMPLETE2\n");
				break;
			case DISPID_BEFORENAVIGATE2:
				pDispatch = (IDispatch *)(pdispparams->rgvarg[nArgIndex--].punkVal);
				pvarString = (VARIANT*)(pdispparams->rgvarg[nArgIndex].byref);
				OnBeforeNavigate(pDispatch,CString(V_BSTR(pvarString)));
				break;
			default:
				hr = DISP_E_PARAMNOTFOUND;
				break;
			}
		}
		else
			hr = DISP_E_PARAMNOTFOUND;

		return hr;
	}
};
#endif
